home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_128 / mrbackup / formatdisk.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  8KB  |  318 lines

  1. /* Format a floppy disk (880k drive).
  2.  * Author:        Mark R. Rinfret
  3.  * Date:        06/28/87
  4.  * Description:
  5.  *        This set of routines may be incorporated into a program which
  6.  *    has need of formatting a floppy disk.  I wrote it to support my
  7.  *    hard disk backup utility.
  8.  *
  9.  * History:        (most recent change first)
  10.  *
  11.  * 08/26/87 -MRR- Modified FormatDisk to delay 5 seconds after
  12.  *                  uninhibiting the drive.  This should give enough time
  13.  *                for the validator to do its thing and prevent the
  14.  *                  "Insert disk..." requester from rearing its ugly head
  15.  *                if the application attempts to access the disk as
  16.  *                soon as we return.
  17.  */
  18.  
  19. #include <exec/types.h>
  20. #include <exec/nodes.h>
  21. #include <exec/lists.h>
  22. #include <exec/memory.h>
  23. #include <exec/interrupts.h>
  24. #include <exec/ports.h>
  25. #include <exec/libraries.h>
  26. #include <exec/io.h>
  27. #include <exec/tasks.h>
  28. #include <exec/execbase.h>
  29. #include <exec/devices.h>
  30. #include <devices/trackdisk.h>
  31. #include <libraries/dosextens.h>
  32. #include <intuition/intuition.h>
  33. #include <functions.h>
  34.  
  35. extern struct IOExtTD *CreateExtIO();
  36.  
  37. static int CkIOErr();
  38.  
  39. /* #define DEBUG */
  40. #define MAX_NAME    30L
  41. #define TD_WRITE    CMD_WRITE
  42. #define TRACKSIZE    NUMSECS * TD_SECTOR
  43.  
  44.  
  45. /* Format a floppy disk - hardwired for the 3.5" 880k floppy drives.
  46.  * Called with:
  47.  *        drivename:    device name (DF0, etc.)
  48.  *      name:        new volume name
  49.  * Returns:
  50.  *        Zero on success, 1 on failure
  51.  * Note:
  52.  *        This routine does not currently perform a verification, as
  53.  *        recommended by the RKM.  Perhaps later...
  54.  *        I also discovered that there's some erroneous crap in 
  55.  *        "The Amiga Programmer's Workbook, Vol. II", by 
  56.  *        Eugene P. Mortimore.  On page 339, he states that only 512
  57.  *        bytes of track data are required for formatting.  The RKM
  58.  *        correctly states that a "track's worth of data" is required.
  59.  *        It took some playing with DiskEd to discover this error.
  60.  */
  61.  
  62. int 
  63. FormatDisk(drivename,name)
  64.     char *drivename; char *name;
  65. {
  66.     long checksum;
  67.     char *dos_id = "DOS";
  68.     long dosword = 0;
  69.     SHORT error;
  70.     struct MsgPort *diskport = NULL;
  71.     struct IOExtTD *diskreq = NULL;
  72.     ULONG diskchangecount;
  73.     struct Process *myprocess;
  74.     struct Window *mywindow;
  75.     USHORT status = 0, i, retry, track;
  76.     int unit; 
  77.     char *volname;
  78.  
  79.     char *diskbuffer;
  80.     ULONG *diskblock;            /* alias for diskbuffer, ULONG type */
  81.  
  82.     if (strlen(name) >= MAX_NAME) {
  83. #ifdef DEBUG
  84.         printf("Disk name is too long!\n");
  85. #endif
  86.         status = ERROR_INVALID_COMPONENT_NAME;    
  87.         goto cleanup;
  88.     }
  89.  
  90.     if ((unit = (drivename[2]-'0')) < 0 || unit >= NUMUNITS) {
  91. #ifdef DEBUG
  92.         printf("FormatDisk: invalid drive specification!\n");
  93. #endif
  94.         status = ERROR_INVALID_COMPONENT_NAME;
  95.         goto cleanup;
  96.     }
  97.  
  98.     if (!(diskbuffer = 
  99.         AllocMem((long) TRACKSIZE, MEMF_PUBLIC | MEMF_CHIP))) {
  100.         status = ERROR_NO_FREE_STORE;
  101.         goto cleanup;
  102.     }
  103.  
  104.     /* Store DOS "magic word" in disk block to be written during
  105.      * formatting. 
  106.      */
  107.     diskblock = (ULONG *) diskbuffer;/* we'll need this later */
  108.     for (i = 0; i < 3; ++i)
  109.         dosword = (dosword << 8) | dos_id[i];
  110.     dosword = dosword << 8;
  111.  
  112. #ifdef DEBUG
  113.     printf("dosword is %lx\n",dosword);
  114. #endif
  115.     for (i = 0; i < TRACKSIZE / 4; ++i)
  116.         diskblock[i] = (dosword | (long) (i & 0xff));
  117.  
  118.     if ((diskport = CreatePort(0L, 0L)) == NULL) {
  119. #ifdef DEBUG
  120.         printf("FormatDisk can't create port!\n");
  121. #endif
  122.         status = 1;                        /* is there a better error code? */
  123.         goto cleanup;
  124.     }
  125.  
  126.     if (!(diskreq = (struct IOExtTD *) 
  127.         CreateExtIO(diskport, (long) sizeof(struct IOExtTD)))) {
  128.         status = 1;
  129.         goto cleanup;
  130.     }
  131.  
  132.     if (status = OpenDevice(TD_NAME, (long) unit, diskreq, 0L)) {
  133. #ifdef DEBUG
  134.         printf("FormatDisk: OpenDevice error: %d\n",error);
  135. #endif
  136.         goto cleanup;
  137.     }
  138.  
  139.     if (status = Inhibit(drivename, 1)) {
  140. #ifdef DEBUG
  141.         printf("FormatDisk: unable to inhibit drive!\n");
  142. #endif
  143.         goto cleanup;
  144.     }
  145.  
  146. /* Get the current disk change count.  This allows the trackdisk
  147.  * driver to detect unwanted disk changes later on.
  148.  */
  149.  
  150.     diskreq->iotd_Req.io_Command = TD_CHANGENUM;
  151.     DoIO(diskreq);
  152.  
  153. /* Save a copy of the disk change count. */
  154.  
  155.     diskchangecount = diskreq->iotd_Req.io_Actual;
  156.  
  157. #ifdef DEBUG
  158.     printf("Current disk change count is %ld\n", diskchangecount);
  159. #endif
  160.  
  161.  
  162.     /* Format the disk, one track at a time. */
  163.  
  164.     for (track = 0; track < NUMTRACKS; ++track) {
  165.         diskreq->iotd_Req.io_Command = TD_FORMAT;
  166.         diskreq->iotd_Req.io_Flags = 0;
  167.         diskreq->iotd_Req.io_Data = (APTR) diskbuffer;
  168.         diskreq->iotd_Count = diskchangecount;
  169.         diskreq->iotd_Req.io_Length = NUMSECS * TD_SECTOR; 
  170.         diskreq->iotd_Req.io_Offset = track * NUMSECS * TD_SECTOR;
  171.         DoIO(diskreq);
  172.  
  173.         if (status = CkIOErr(diskreq,"Formatting error")) {
  174. #ifdef DEBUG
  175.             printf("  Track: %d\n",track);
  176. #endif
  177.             goto cleanup;
  178.         }
  179.     }
  180.  
  181.     /* Now comes some real KLUDGING.  Fill in the root block and the
  182.      * first hash block.  The information for this was gathered from
  183.      * the "AmigaDos Technical Reference Manual" and some sleuthing
  184.      * with DiskEd.
  185.      */
  186.  
  187.     for (i = 0; i < 128; ++i)
  188.         diskblock[i] = 0;
  189.  
  190.     diskblock[0] = 2;            /* T.SHORT (type) */
  191.     diskblock[3] = 128 - 56;    /* hashtable size */
  192.     diskblock[78] = 0xffffffff; /* BMFLAG */
  193.     diskblock[79] = 881;        /* first bitmap block */
  194.     DateStamp(&diskblock[105]);    /* volume last altered date/time */
  195.     DateStamp(&diskblock[121]); /* volume creation date/time */
  196.     volname = (char *) &diskblock[108];
  197.     /* convert input name to BSTR */
  198.     *volname = strlen(name);
  199.     for (i = 0; i < *volname; ++i)
  200.         *(volname + 1 + i) = *(name + i);
  201.  
  202.     diskblock[127] = 1;            /* ST.ROOT (secondary type) */
  203.  
  204.     checksum = 0;
  205.     for (i = 0; i < 128; ++i)
  206.         checksum += diskblock[i];
  207.  
  208.     diskblock[5] = - checksum;
  209.  
  210.     /* Write the root block out to the disk. */
  211.  
  212.     diskreq->iotd_Req.io_Command = TD_WRITE;
  213.     diskreq->iotd_Req.io_Length = TD_SECTOR;
  214.     diskreq->iotd_Req.io_Offset = TD_SECTOR * 880L;
  215.     DoIO(diskreq);
  216.     if (status = CkIOErr(diskreq, "Error writing root block")) {
  217.         goto cleanup;
  218.     }
  219.  
  220.     /* Write the first bitmap block. */
  221.  
  222.     for (i = 0; i < 56; ++i)
  223.         diskblock[i] = 0xffffffff;
  224.  
  225.     for (i = 56; i < 128; ++i)
  226.         diskblock[i] = 0;
  227.  
  228.     diskblock[0] = 0xc000c037;    /* hint: x37 = 55 (last word of map?) */
  229.     diskblock[28] = 0xffff3fff; /* blocks 880, 881 used */
  230.     diskblock[55] = 0x3fffffff; /* blocks 1760, 1761 used? */
  231.  
  232.     diskreq->iotd_Req.io_Length = TD_SECTOR;
  233.     diskreq->iotd_Req.io_Offset = 881L * TD_SECTOR;
  234.     DoIO(diskreq);                    /* write out the bitmap */
  235.     if (status = CkIOErr(diskreq, "Error writing bitmap")) {
  236.         goto cleanup;
  237.     }
  238.  
  239.     diskreq->iotd_Req.io_Command = ETD_UPDATE;
  240.     diskreq->iotd_Req.io_Flags = 0;
  241.     DoIO(diskreq);
  242.  
  243.     /* Turn the disk motor off. */
  244.  
  245.     diskreq->iotd_Req.io_Command = TD_MOTOR;
  246.     diskreq->iotd_Req.io_Length = 0;
  247.     DoIO(diskreq);
  248.     Inhibit(drivename, 0);                /* enable disk validator */
  249.  
  250.     Delay(3L * TICKS_PER_SECOND);        /* Give it a chance */
  251.  
  252. cleanup:
  253.     CloseDevice(diskreq);
  254.     if (diskbuffer) FreeMem(diskbuffer, (long) TRACKSIZE);
  255.     if (diskreq) DeleteExtIO(diskreq, (long) sizeof(*diskreq));
  256.     if (diskport) DeletePort(diskport);
  257.     return status;
  258. }
  259.  
  260. /* Check the disk request block for an error code.  If an error
  261.  * occurred, print the argument string.
  262.  * Called with:
  263.  *        req:    pointer to I/O request structure
  264.  *        msg:    error message string
  265.  * Returns:
  266.  *        error code from request structure
  267.  */
  268. static int CkIOErr(req, msg)
  269.     struct IOStdReq *req; char *msg;
  270. {
  271.     register int code;
  272.  
  273.     if (code = req->io_Error) {
  274. #ifdef DEBUG
  275.         printf("%s, code: %d\n",msg,code);
  276. #endif
  277.     }
  278.     return code;
  279. }
  280.  
  281. #ifdef DEBUG
  282. main(argc, argv)
  283.     int argc; char *argv[];
  284. {
  285.     char *diskname;
  286.     char *volname;
  287.  
  288.     int unit;
  289.  
  290.     if (argc < 3)
  291.         volname = "GoodJob!";
  292.     else
  293.         volname = argv[2];
  294.  
  295.     if (argc < 2)
  296.         diskname = "DF1:";
  297.     else {
  298.         diskname = argv[1];
  299.         if (strlen(diskname) != 4 || 
  300.             (strncmp(diskname,"df",2) && strncmp(diskname,"DF",2))) {
  301. bad_drive:
  302.             printf("Drive name may only be df0: through df3:!\n");
  303.             exit(1);
  304.         }
  305.         if ((unit = (diskname[2] - '0')) < 0 || unit > 3)
  306.             goto bad_drive;
  307.  
  308.     }
  309.     printf("Insert disk in %s, then hit return\n",diskname);
  310.     while (getchar() != '\n');
  311.     if (FormatDisk(diskname,volname))
  312.         printf("FormatDisk failed\n");
  313.     else {
  314.         printf("FormatDisk succeeded\n");
  315.     }
  316. }
  317. #endif
  318.